#include <net.h>
#include <os/string.h>
#include <screen.h>
#include <emacps/xemacps_example.h>
#include <emacps/xemacps.h>

#include <os/sched.h>
#include <os/mm.h>

EthernetFrame rx_buffers[RXBD_CNT];
EthernetFrame tx_buffer;
uint32_t rx_len[RXBD_CNT];

int net_poll_mode;

volatile int rx_curr = 0, rx_tail = 0;

uintptr_t k_addr;
int packet_need;
int irq_num_received;
size_t* k_length;


long do_net_recv(uintptr_t addr, size_t length, int num_packet, size_t* frLength)
{
    // TODO: 
    // receive packet by calling network driver's function
    // wait until you receive enough packets(`num_packet`).
    // maybe you need to call drivers' receive function multiple times ?
    k_addr = get_kva_of(addr, current_running->pgdir);
    packet_need = (num_packet > 32) ? 32 : num_packet;
    irq_num_received = 0;
    k_length = get_kva_of((uintptr_t)frLength, current_running->pgdir);
    EmacPsRecv(&EmacPsInstance, rx_buffers, packet_need);
    EmacPsWaitRecv(&EmacPsInstance, packet_need, rx_len);
    if(!irq_mode)
        net_recv_memcpy(k_addr, packet_need, k_length);
    return 1;
}

void do_net_send(uintptr_t addr, size_t length)
{
    // TODO:
    // send all packet
    // maybe you need to call drivers' send function multiple times ?
    kmemcpy(&tx_buffer, addr, length);
    EmacPsSend(&EmacPsInstance, &tx_buffer ,length);
    EmacPsWaitSend(&EmacPsInstance);
}

void do_net_irq_mode(int mode)
{
    // TODO:
    // turn on/off network driver's interrupt mode
    set_irq_mode(&EmacPsInstance, mode);
}

void net_recv_memcpy(uintptr_t addr, int num_packet, size_t* frLength)
{
    for (int i = 0; i < num_packet; i++){
        kmemcpy(addr, &rx_buffers[i], rx_len[i]);
        *frLength = rx_len[i];
        frLength ++;
        addr += rx_len[i];
    }
}